import os
import subprocess
import time
import json
import re
import requests
import hashlib
import getpass
from pathlib import Path
from datetime import datetime
import difflib
import webbrowser
import traceback

class UserManager:
    """用户管理系统"""
    def __init__(self, data_dir=None):
        # 使用当前工作目录
        if data_dir is None:
            self.data_dir = Path.cwd() / "user_data"
        else:
            self.data_dir = Path(data_dir)
        
        # 确保目录存在
        self.data_dir.mkdir(parents=True, exist_ok=True)
        
        self.users_file = self.data_dir / "users.json"
        self.current_user = None
        self.users = self.load_users()
    
    def load_users(self):
        """加载用户数据"""
        if self.users_file.exists():
            try:
                with open(self.users_file, "r") as f:
                    return json.load(f)
            except:
                pass
        return {}
    
    def save_users(self):
        """保存用户数据"""
        with open(self.users_file, "w") as f:
            json.dump(self.users, f, indent=2)
    
    def hash_password(self, password):
        """密码哈希处理"""
        return hashlib.sha256(password.encode()).hexdigest()
    
    def register(self, username, password):
        """注册新用户"""
        if username in self.users:
            return False, "用户名已存在"
        
        if len(username) < 3:
            return False, "用户名至少需要3个字符"
        
        if len(password) < 6:
            return False, "密码至少需要6个字符"
        
        # 创建用户目录
        user_dir = self.data_dir / username
        user_dir.mkdir(parents=True, exist_ok=True)
        
        # 保存用户信息
        self.users[username] = {
            "password_hash": self.hash_password(password),
            "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "last_login": None
        }
        
        # 初始化用户配置
        config = {
            "selected_model": None,
            "api_keys": {},
            "auto_save_versions": True,
            "max_history": 10,
            "web_port": 5000,
            "auto_open_browser": True
        }
        config_path = user_dir / "config.json"
        with open(config_path, "w") as f:
            json.dump(config, f, indent=2)
        
        self.save_users()
        return True, "注册成功"
    
    def login(self, username, password):
        """用户登录"""
        if username not in self.users:
            return False, "用户名不存在"
        
        stored_hash = self.users[username]["password_hash"]
        if self.hash_password(password) != stored_hash:
            return False, "密码错误"
        
        # 更新最后登录时间
        self.users[username]["last_login"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.save_users()
        
        self.current_user = username
        return True, f"欢迎回来，{username}!"
    
    def logout(self):
        """用户登出"""
        if self.current_user:
            username = self.current_user
            self.current_user = None
            return True, f"{username} 已登出"
        return False, "没有登录的用户"
    
    def get_user_dir(self):
        """获取当前用户目录"""
        if not self.current_user:
            return None
        return self.data_dir / self.current_user

class AIDeveloper:
    OPERATION_TYPES = [
        "create_file", "modify_file", "delete_file", 
        "run_command", "run_code", "debug_code",
        "explain", "web_server", "open_browser"
    ]
    
    def __init__(self, user_dir):
        self.user_dir = Path(user_dir)
        self.workspace = self.user_dir / "projects"
        self.workspace.mkdir(parents=True, exist_ok=True)
        self.versions_dir = self.user_dir / "versions"
        self.versions_dir.mkdir(parents=True, exist_ok=True)
        self.project_history = []
        self.current_file = None
        self.current_project = "default"
        self.current_project_type = "python"
        self.config = self.load_config()
        self.web_process = None
        self.web_port = self.config.get("web_port", 5000)
        
        # 支持的AI模型服务
        self.supported_models = {
            "deepseek": {
                "name": "DeepSeek",
                "endpoint": "https://api.deepseek.com/v1/chat/completions",
                "model": "deepseek-coder"
            },
            "wenxin": {
                "name": "文心千帆",
                "endpoint": "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions",
                "model": "ERNIE-Bot-4"
            }
        }
    
    def load_config(self):
        """加载用户配置"""
        config_path = self.user_dir / "config.json"
        if config_path.exists():
            try:
                with open(config_path, "r") as f:
                    return json.load(f)
            except:
                pass
        
        # 默认配置
        default_config = {
            "selected_model": None,
            "api_keys": {},
            "auto_save_versions": True,
            "max_history": 10,
            "web_port": 5000,
            "auto_open_browser": True
        }
        
        # 保存默认配置
        with open(config_path, "w") as f:
            json.dump(default_config, f, indent=2)
        
        return default_config
    
    def save_config(self):
        """保存用户配置"""
        config_path = self.user_dir / "config.json"
        with open(config_path, "w") as f:
            json.dump(self.config, f, indent=2)
    
    def display_banner(self, username):
        print("\033[1;34m" + "=" * 70)
        print(f"        AI 程序员智能开发系统 v6.0 (指令驱动版)")
        print("=" * 70 + "\033[0m")
        print(f"用户: \033[1;32m{username}\033[0m")
        print(f"工作区: \033[1;33m{self.workspace}\033[0m")
        
        if self.config["selected_model"]:
            model_name = self.supported_models.get(self.config["selected_model"], {}).get("name", "未知模型")
            print(f"当前模型: \033[1;32m{model_name}\033[0m")
        else:
            print("当前模型: \033[1;31m未配置\033[0m (使用内置逻辑)")
        
        print("\n指令格式: JSON对象，包含以下操作类型:")
        for op in self.OPERATION_TYPES:
            print(f" - {op}")
        print("\n输入 'exit' 退出系统")
        print("输入 'help' 显示帮助")
    
    def log_history(self, action, content, details=None):
        """记录开发历史"""
        timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
        entry = {
            "time": timestamp,
            "action": action,
            "content": content,
            "details": details
        }
        self.project_history.append(entry)
        
        # 保持历史记录不超过最大值
        if len(self.project_history) > self.config.get("max_history", 20):
            self.project_history.pop(0)
        
        # 保存历史到文件
        history_path = self.user_dir / "dev_history.json"
        with open(history_path, "w") as f:
            json.dump(self.project_history, f, indent=2)
    
    def save_version(self, action="自动保存"):
        """保存当前代码版本"""
        if not self.current_file or not self.current_file.exists():
            return None
        
        # 读取当前文件内容
        with open(self.current_file, "r", encoding="utf-8") as f:
            current_code = f.read()
        
        # 创建版本文件名
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        version_file = self.versions_dir / f"{self.current_project}_{timestamp}.py"
        
        # 保存版本
        with open(version_file, "w", encoding="utf-8") as f:
            f.write(current_code)
        
        return version_file.name
    
    def call_ai_api(self, prompt, system_prompt=None):
        """调用选定的AI模型API"""
        if not self.config["selected_model"] or not self.config["api_keys"].get(self.config["selected_model"]):
            return None
        
        model_info = self.supported_models[self.config["selected_model"]]
        api_key = self.config["api_keys"][self.config["selected_model"]]
        
        headers = {
            "Content-Type": "application/json"
        }
        
        # 默认系统提示
        if not system_prompt:
            system_prompt = """
            你是一个AI程序员，需要根据用户需求生成JSON格式的操作指令。
            请严格按照以下JSON格式返回响应：
            
            {
                "reasoning": "思考过程，解释为什么这么做",
                "operations": [
                    {
                        "type": "操作类型",
                        "path": "文件路径",
                        "content": "文件内容（可选）",
                        "command": "系统命令（可选）",
                        "explanation": "操作说明（可选）"
                    },
                    // 更多操作...
                ]
            }
            
            支持的操作类型:
            - create_file: 创建新文件，需要path和content
            - modify_file: 修改文件，需要path和content
            - delete_file: 删除文件，需要path
            - run_command: 执行系统命令，需要command
            - run_code: 运行代码文件，需要path
            - debug_code: 调试代码，需要path（可选content）
            - explain: 解释代码或操作，需要explanation
            - web_server: 启动Web服务器，需要path（主文件）
            - open_browser: 打开浏览器，需要path（URL或文件路径）
            """
        
        messages = [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": prompt}
        ]
        
        if self.config["selected_model"] == "deepseek":
            headers["Authorization"] = f"Bearer {api_key}"
            payload = {
                "model": model_info["model"],
                "messages": messages,
                "temperature": 0.3,
                "max_tokens": 4000,
                "response_format": {"type": "json_object"}
            }
        elif self.config["selected_model"] == "wenxin":
            payload = {
                "messages": messages,
                "temperature": 0.3,
                "max_tokens": 4000
            }
            # 文心千帆API需要access_token
            access_token = self.get_wenxin_access_token(api_key)
            if not access_token:
                return None
            endpoint = f"{model_info['endpoint']}?access_token={access_token}"
        else:
            return None
        
        try:
            response = requests.post(
                model_info["endpoint"] if self.config["selected_model"] == "deepseek" else endpoint,
                headers=headers,
                json=payload,
                timeout=60
            )
            
            if response.status_code == 200:
                result = response.json()
                if self.config["selected_model"] == "deepseek":
                    return result["choices"][0]["message"]["content"]
                elif self.config["selected_model"] == "wenxin":
                    return result["result"]
            else:
                print(f"API错误: {response.status_code} - {response.text}")
                return None
        except Exception as e:
            print(f"API调用异常: {str(e)}")
            return None
    
    def get_wenxin_access_token(self, api_key):
        """获取文心千帆的access_token"""
        if ":" not in api_key:
            return None
        
        api_key, secret_key = api_key.split(":", 1)
        url = "https://aip.baidubce.com/oauth/2.0/token"
        params = {
            "grant_type": "client_credentials",
            "client_id": api_key,
            "client_secret": secret_key
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            if response.status_code == 200:
                return response.json().get("access_token")
        except:
            pass
        return None
    
    def parse_ai_response(self, response):
        """解析AI的JSON响应"""
        try:
            # 尝试提取JSON对象
            start_idx = response.find('{')
            end_idx = response.rfind('}')
            if start_idx != -1 and end_idx != -1:
                json_str = response[start_idx:end_idx+1]
                return json.loads(json_str)
        except json.JSONDecodeError as e:
            print(f"JSON解析错误: {str(e)}")
        
        # 返回默认结构
        return {
            "reasoning": "无法解析AI响应",
            "operations": [{
                "type": "explain",
                "explanation": f"AI返回了无效响应: {response[:200]}..."
            }]
        }
    
    def execute_operations(self, operations):
        """执行AI返回的操作指令"""
        results = []
        
        for op in operations:
            op_type = op.get("type", "")
            path = op.get("path", "")
            content = op.get("content", "")
            command = op.get("command", "")
            explanation = op.get("explanation", "")
            
            result = {"type": op_type, "success": False, "output": ""}
            
            try:
                # 创建文件
                if op_type == "create_file":
                    full_path = self.workspace / path
                    full_path.parent.mkdir(parents=True, exist_ok=True)
                    
                    # 检查文件是否已存在
                    if full_path.exists():
                        result["output"] = f"文件已存在: {path}"
                    else:
                        with open(full_path, "w", encoding="utf-8") as f:
                            f.write(content)
                        result["success"] = True
                        result["output"] = f"文件创建成功: {path}"
                        self.current_file = full_path
                
                # 修改文件
                elif op_type == "modify_file":
                    full_path = self.workspace / path
                    if full_path.exists():
                        # 保存当前版本
                        if self.config["auto_save_versions"]:
                            self.save_version("修改前保存")
                        
                        with open(full_path, "w", encoding="utf-8") as f:
                            f.write(content)
                        result["success"] = True
                        result["output"] = f"文件修改成功: {path}"
                        self.current_file = full_path
                    else:
                        result["output"] = f"文件不存在: {path}"
                
                # 删除文件
                elif op_type == "delete_file":
                    full_path = self.workspace / path
                    if full_path.exists():
                        # 保存当前版本
                        if self.config["auto_save_versions"]:
                            self.save_version("删除前保存")
                            
                        full_path.unlink()
                        result["success"] = True
                        result["output"] = f"文件删除成功: {path}"
                    else:
                        result["output"] = f"文件不存在: {path}"
                
                # 执行系统命令
                elif op_type == "run_command":
                    try:
                        process = subprocess.run(
                            command,
                            shell=True,
                            capture_output=True,
                            text=True,
                            timeout=30
                        )
                        result["output"] = process.stdout
                        if process.returncode == 0:
                            result["success"] = True
                        else:
                            result["output"] += f"\n错误: {process.stderr}"
                    except Exception as e:
                        result["output"] = f"命令执行失败: {str(e)}"
                
                # 运行代码
                elif op_type == "run_code":
                    full_path = self.workspace / path
                    if full_path.exists():
                        try:
                            process = subprocess.run(
                                ["python", str(full_path)],
                                capture_output=True,
                                text=True,
                                timeout=30
                            )
                            result["output"] = process.stdout
                            if process.returncode == 0:
                                result["success"] = True
                            else:
                                result["output"] += f"\n错误: {process.stderr}"
                        except Exception as e:
                            result["output"] = f"代码运行失败: {str(e)}"
                    else:
                        result["output"] = f"文件不存在: {path}"
                
                # 调试代码
                elif op_type == "debug_code":
                    # 这里简化处理，实际应该调用调试逻辑
                    result["output"] = "调试功能将在后续版本实现"
                
                # 解释说明
                elif op_type == "explain":
                    result["success"] = True
                    result["output"] = explanation
                
                # 启动Web服务器
                elif op_type == "web_server":
                    full_path = self.workspace / path
                    if full_path.exists():
                        # 停止现有服务器
                        if self.web_process and self.web_process.poll() is None:
                            self.web_process.terminate()
                        
                        # 启动新服务器
                        self.web_process = subprocess.Popen(
                            ["python", str(full_path)],
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE,
                            text=True
                        )
                        time.sleep(2)
                        
                        if self.web_process.poll() is None:
                            result["success"] = True
                            result["output"] = f"Web服务器已启动: http://localhost:{self.web_port}"
                        else:
                            error = self.web_process.stderr.read() if self.web_process.stderr else "启动失败"
                            result["output"] = f"Web服务器启动失败: {error}"
                    else:
                        result["output"] = f"文件不存在: {path}"
                
                # 打开浏览器
                elif op_type == "open_browser":
                    if path.startswith("http"):
                        webbrowser.open(path)
                        result["success"] = True
                        result["output"] = f"已打开浏览器: {path}"
                    else:
                        full_path = self.workspace / path
                        if full_path.exists():
                            webbrowser.open(f"file://{full_path.resolve()}")
                            result["success"] = True
                            result["output"] = f"已打开文件: {path}"
                        else:
                            result["output"] = f"文件不存在: {path}"
                
                # 未知操作类型
                else:
                    result["output"] = f"未知操作类型: {op_type}"
            
            except Exception as e:
                result["output"] = f"操作执行异常: {str(e)}\n{traceback.format_exc()}"
            
            results.append(result)
        
        return results
    
    def generate_instructions(self, requirements):
        """根据需求生成操作指令并执行"""
        # 构建提示
        prompt = f"""
        用户需求: {requirements}
        
        当前工作区: {self.workspace}
        当前项目: {self.current_project}
        当前文件: {self.current_file}
        
        请生成JSON格式的操作指令来满足用户需求。
        """
        
        # 调用AI API
        ai_response = self.call_ai_api(prompt)
        if not ai_response:
            return {
                "reasoning": "AI调用失败",
                "operations": [{
                    "type": "explain",
                    "explanation": "无法调用AI服务，请检查API配置"
                }]
            }, []
        
        # 解析AI响应
        instructions = self.parse_ai_response(ai_response)
        
        # 执行操作
        results = self.execute_operations(instructions.get("operations", []))
        
        return instructions, results
    
    def process_requirements(self, requirements):
        """处理用户需求"""
        if requirements.lower() == 'exit':
            return "系统已退出", True
        
        if requirements.lower() == 'help':
            help_text = """
            ### 系统帮助 ###
            1. 输入需求描述，AI将生成操作指令
            2. 支持的操作类型:
               - create_file: 创建文件
               - modify_file: 修改文件
               - delete_file: 删除文件
               - run_command: 执行命令
               - run_code: 运行代码
               - debug_code: 调试代码
               - explain: 解释说明
               - web_server: 启动Web服务器
               - open_browser: 打开浏览器
            3. 系统命令:
               - exit: 退出系统
               - help: 显示帮助
               - config: 配置模型
               - history: 查看历史
            """
            return help_text, False
        
        if requirements.lower() == 'config':
            return self.configure_model(), False
        
        if requirements.lower() == 'history':
            return self.show_history(), False
        
        # 生成指令并执行
        instructions, results = self.generate_instructions(requirements)
        
        # 准备响应
        response = "\n\033[1;34m=== AI推理过程 ===\033[0m\n"
        response += instructions.get("reasoning", "无推理过程") + "\n\n"
        
        response += "\033[1;34m=== 执行结果 ===\033[0m\n"
        for i, result in enumerate(results, 1):
            status = "\033[1;32m✓\033[0m" if result["success"] else "\033[1;31m✗\033[0m"
            response += f"{i}. [{status}] {result['type']}: {result['output']}\n"
        
        # 记录历史
        self.log_history("执行指令", requirements, {
            "instructions": instructions,
            "results": results
        })
        
        return response, False
    
    def show_history(self):
        """显示开发历史"""
        if not self.project_history:
            return "尚无开发历史"
        
        history_str = ""
        for i, entry in enumerate(self.project_history[-5:]):  # 显示最近5条记录
            history_str += f"{i+1}. [{entry['time']}] {entry['action']}: {entry['content'][:50]}"
            if len(entry['content']) > 50:
                history_str += "..."
            history_str += "\n"
        return history_str
    
    def configure_model(self):
        """配置AI模型和API密钥"""
        print("\n\033[1;36m===== 模型配置 =====\033[0m")
        print("支持的AI模型服务:")
        for i, (key, model) in enumerate(self.supported_models.items(), 1):
            print(f"{i}. {model['name']} ({key})")
        print("0. 不使用AI模型 (使用内置逻辑)")
        
        try:
            choice = int(input("\n请选择要使用的模型 (编号): "))
            if choice == 0:
                self.config["selected_model"] = None
                self.save_config()
                return "已设置为使用内置逻辑"
            
            model_keys = list(self.supported_models.keys())
            if 1 <= choice <= len(model_keys):
                selected_key = model_keys[choice-1]
                self.config["selected_model"] = selected_key
                
                # 获取API密钥
                api_key = input(f"请输入{self.supported_models[selected_key]['name']}的API密钥: ").strip()
                if api_key:
                    self.config["api_keys"][selected_key] = api_key
                    self.save_config()
                    return f"{self.supported_models[selected_key]['name']}配置成功!"
                else:
                    return "未提供API密钥，配置未保存"
            else:
                return "无效的选择"
        except ValueError:
            return "输入无效，请输入数字"

def main():
    # 使用当前工作目录创建UserManager
    user_manager = UserManager()
    
    # 用户认证流程
    print("\033[1;34m" + "=" * 70)
    print("        AI 程序员智能开发系统 v6.0 (指令驱动版)")
    print("=" * 70 + "\033[0m")
    
    while not user_manager.current_user:
        print("\n请选择操作:")
        print("1. 登录")
        print("2. 注册")
        print("3. 退出")
        
        choice = input("请输入选项编号: ").strip()
        
        if choice == "1":  # 登录
            username = input("用户名: ").strip()
            password = getpass.getpass("密码: ").strip()
            success, message = user_manager.login(username, password)
            if success:
                print(f"\033[1;32m{message}\033[0m")
            else:
                print(f"\033[1;31m{message}\033[0m")
                
        elif choice == "2":  # 注册
            username = input("用户名: ").strip()
            password = getpass.getpass("密码: ").strip()
            confirm = getpass.getpass("确认密码: ").strip()
            
            if password != confirm:
                print("\033[1;31m两次输入的密码不一致\033[0m")
                continue
                
            success, message = user_manager.register(username, password)
            if success:
                print(f"\033[1;32m{message}\033[0m")
                # 自动登录新用户
                user_manager.login(username, password)
            else:
                print(f"\033[1;31m{message}\033[0m")
                
        elif choice == "3":  # 退出
            print("系统已退出")
            return
            
        else:
            print("\033[1;31m无效选项，请重新输入\033[0m")
    
    # 初始化AI开发者环境
    user_dir = user_manager.get_user_dir()
    if not user_dir:
        print("\033[1;31m无法获取用户目录，请重新登录\033[0m")
        return
        
    ai_dev = AIDeveloper(user_dir)
    ai_dev.display_banner(user_manager.current_user)
    
    while True:
        try:
            requirements = input("\n\033[1;32m请输入需求 (\033[1;33m'help' 显示帮助\033[1;32m): \033[0m")
            
            if requirements.lower() == 'logout':
                result, message = user_manager.logout()
                print(f"\033[1;32m{message}\033[0m")
                # 重新启动主函数以返回登录界面
                main()
                return
                
            response, should_exit = ai_dev.process_requirements(requirements)
            
            print("\033[1;36m" + response + "\033[0m")
            
            if should_exit:
                break
                
        except KeyboardInterrupt:
            print("\n\033[1;33m操作已中断。输入 'exit' 退出系统。\033[0m")
        except Exception as e:
            print(f"\033[1;31m发生错误: {str(e)}\033[0m")
    
    # 退出前停止Web服务器
    if ai_dev.web_process and ai_dev.web_process.poll() is None:
        ai_dev.web_process.terminate()
    print("\033[1;32m系统已退出\033[0m")

if __name__ == "__main__":
    main()